import os
import shutil
import sys
import subprocess
import yaml
import requests
import tarfile
import pwd


class OpRedis:
    def __init__(self):
        with open(os.path.join(os.path.dirname(__file__), "redis.yaml"), encoding='utf-8') as f:
            yamldict = yaml.load(f, Loader=yaml.Loader)
            self.yamldict = yamldict

    def onlydown(self):
        donwload = self.yamldict['donwload']
        filepath = self.yamldict['filepath']

        res_length = requests.get(donwload, stream=True)
        total_size = int(res_length.headers['Content-Length'])
        if os.path.exists(filepath):
            temp_size = os.path.getsize(filepath)
            print("当前：%d 字节， 总：%d 字节， 已下载：%2.2f%% " % (temp_size, total_size, 100 * temp_size / total_size))
        else:
            temp_size = 0
            print("总：%d 字节，开始下载..." % (total_size,))
        headers = {'Range': 'bytes=%d-' % temp_size,
                   "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0"}
        res_left = requests.get(donwload, stream=True, headers=headers)
        with open(filepath, mode='ab') as f:
            for chunk in res_left.iter_content(chunk_size=1024):
                temp_size += len(chunk)
                f.write(chunk)
                f.flush()

                done = int(50 * temp_size / total_size)
                sys.stdout.write("\r[%s%s] %d%%" % ('█' * done, ' ' * (50 - done), 100 * temp_size / total_size))
                sys.stdout.flush()

    def initconf(self):
        basepath = self.yamldict['basepath']
        datapath = self.yamldict['datapath']
        logpath = self.yamldict['logpath']
        requirepass = self.yamldict['requirepass']
        password = self.yamldict['password']
        type = self.yamldict['type']
        hosts = self.yamldict['hosts']

        if not os.path.exists(datapath):
            os.makedirs(datapath)

        if not os.path.exists(os.path.dirname(logpath)):
            os.makedirs(os.path.dirname(logpath))

        if type == "single" and len(hosts) == 1:
            print("开始生成单机配置文件...")
            for h in hosts:
                ip = h.strip(":")[:9]
                port = h.strip(":")[10:]

            with open(os.path.join(os.path.dirname(__file__), "redis.conf"), mode="r") as rf:
                with open(os.path.join(basepath, "redis.conf"), mode="w") as wf:
                    # with open(os.path.join(os.path.dirname(__file__), "redis1.conf"), mode="w") as wf:

                    for line in rf.readlines():
                        if line.startswith("bind"):
                            wf.write(line.replace("bind 127.0.0.1", "bind {}".format(ip)))
                            continue
                        if line.startswith("port"):
                            wf.write(line.replace("port 6379", "port {}".format(port)))
                            continue
                        if line.startswith("logfile"):
                            wf.write(line.replace('logfile ""', 'logfile "{}"'.format(logpath)))
                            continue
                        if line.startswith("dir"):
                            wf.write(line.replace('dir ./', 'dir {}/'.format(datapath)))
                            continue
                        if line.startswith("#requirepass") and (requirepass == 1):
                            wf.write(line.replace('#requirepass', 'requirepass {}'.format(password)))
                            continue
                        wf.write(line)
            print("生成单机配置文件成功！")

        if type == "cluster" and len(hosts) >= 1:
            print("开始部署集群")
            # todo

        if type != "single" and type != "cluster":
            print("配置有误，请检查！")
            exit(99)

    def install(self):
        self.onlydown()
        basepath = self.yamldict['basepath']
        filepath = self.yamldict['filepath']
        type = self.yamldict['type']

        currdir = os.getcwd()

        if type == "single":
            print("开始安装redis单机版")
            try:
                # res = subprocess.run(["tar", "xzf", filepath, "-C", "/tmp/"])
                # if res.returncode == 0:
                #    print("解压{}到/tmp/成功".format(filepath))

                tar = tarfile.open(filepath, "r:gz")
                filenames = tar.getnames()
                for filename in filenames:
                    tar.extract(filename, '/tmp')
                tar.close()
                print("解压{}到/tmp成功".format(filepath))

                tmp_path = os.path.join("/tmp/",
                                        os.popen("ls /tmp/ | grep 'redis-[0-9].[0-9].[0-9]'").read().strip("\n"))
                os.chdir(tmp_path)
                res = os.system("make PREFIX={} install".format(basepath))
                if res == 0:
                    print("redis单机版安装成功")

                os.chdir(currdir)
                self.initconf()

                # 删除/tmp下的redis包
                shutil.rmtree(tmp_path)

            except Exception as e:
                print(e)

    def start(self):
        runuser = self.yamldict['runuser']
        basepath = self.yamldict['basepath']
        datapath = self.yamldict['datapath']
        logpath = self.yamldict['logpath']

        res = subprocess.run(["useradd", runuser, "-M", "-s", "/sbin/nologin"])
        if res.returncode == 0 or res.returncode == 9:
            print(runuser, "用户创建成功或已经存在")
        else:
            print(runuser, "用户创建失败")
            exit(99)

        myGroupId = pwd.getpwnam(runuser).pw_gid
        os.chown(basepath, myGroupId, myGroupId)
        os.chown(os.path.dirname(logpath), myGroupId, myGroupId)
        os.chown(datapath, myGroupId, myGroupId)
        for root, dirs, files in os.walk(basepath):
            for momo in dirs:
                os.chown(os.path.join(root, momo), myGroupId, myGroupId)
            for momo in files:
                os.lchown(os.path.join(root, momo), myGroupId, myGroupId)

        if not os.path.exists("/usr/lib/systemd/system/redis.service"):
            with open(os.path.join(os.path.dirname(__file__), "redis.service"), mode="r") as rf:
                with open("/usr/lib/systemd/system/redis.service", mode="w") as wf:
                    for line in rf.readlines():
                        if line.startswith("User="):
                            wf.write(line.replace("User=myuser", "User={}".format(runuser)))
                            continue
                        if line.startswith("Group="):
                            wf.write(line.replace("Group=myuser", "Group={}".format(runuser)))
                            continue
                        if line.startswith("ExecStart="):
                            wf.write(line.replace("ExecStart=/path/bin/redis-server /path/redis.conf",
                                                  "ExecStart={}/bin/redis-server {}/redis.conf".format(basepath, basepath)))
                            continue
                        wf.write(line)
            print("/usr/lib/systemd/system/redis.service配置完成")
        else:
            print("/usr/lib/systemd/system/redis.service已存在，跳过...")

        os.system("systemctl daemon-reload")
        os.system("systemctl enable redis.service")
        os.system("systemctl start redis.service")
        print("redis启动完成，systemctl start|stop|restart|status|reload redis")


if __name__ == '__main__':
    r = OpRedis()
    r.install()
    r.start()
